/*
* Copyright (c) 2009, Ander Ruiz & Alexander Benito
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * - Neither the name of Mauricio Aguilar O. nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @author: Ander Ruiz y Alexander Benito
 * email  : anderruiz@yahoo.es
 * Date   : May 31 , 2009
 *
 */

package org.transFX.scene.paint;

import java.lang.Math;
import javafx.scene.paint.Color;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Paint;
import javafx.scene.paint.CycleMethod;

/**
 * @author Ander
 */

public class CoolGradient {

    var firstColor:Color;
    var secondColor:Color;
    var thirdColor:Color;

    public-init var firstScaling = 3.2;
    public-init var secondScaling = 1.5;
    public-init var thirdScaling = 2.1;

    var redPos:Integer;
    var greenPos:Integer;
    var bluePos:Integer;

    public-init var firstMax = 255.0;
    public-init var secondMax:Number = 178.0;
    public-init var thirdMax = 244.0;

    public-init var linearGradient:Boolean = true;
    public-init var radialCenterX = 0.5;
    public-init var radialCenterY = 0.5;

    public-init var linearEndX = 0.0;
    public-init var linearEndY = 1.0;

    public-init var baseColor:Color on replace
    {
        def baseRed = baseColor.red * 255;
        def baseBlue = baseColor.blue * 255;
        def baseGreen = baseColor.green * 255;
        def maximun = max(baseRed, baseBlue, baseGreen);
        secondMax = (firstMax - maximun) * 0.2 + maximun;
        def firstScale = firstMax / maximun;
        def secondScale = secondMax / maximun;
        def thirdScale = thirdMax / maximun;
        var orderedColors = makeSequence(baseRed, baseGreen, baseBlue);
        var mainDifference:Number = orderedColors[0]-orderedColors[2];
        var secondDifference:Number = orderedColors[0]-orderedColors[1];
        var firstSequence:Number[];
        var secondSequence:Number[];
        var thirdSequence:Number[];
        var i:Integer = 0;
        while(i < sizeof orderedColors)
        {
            if(i==0)
            {
                insert (firstMax - (mainDifference / firstScaling)) into firstSequence;
                insert (secondMax - (mainDifference / secondScaling)) into secondSequence;
                insert (thirdMax - (mainDifference / thirdScaling)) into thirdSequence;
            }
            else if(i==1)
            {
                insert (firstMax- (secondDifference / firstScaling)) into firstSequence;
                insert (secondMax - (secondDifference / secondScaling)) into secondSequence;
                insert (thirdMax - (secondDifference / thirdScaling)) into thirdSequence;
            }
            else
            {
                insert firstMax into firstSequence;
                insert secondMax into secondSequence;
                insert thirdMax into thirdSequence;
            }
            i++;
        }

        firstColor = Color.rgb(firstSequence[2-redPos], firstSequence[2-greenPos], firstSequence[2-bluePos]);
        secondColor = Color.rgb(secondSequence[2-redPos], secondSequence[2-greenPos], secondSequence[2-bluePos]);
        thirdColor = Color.rgb(thirdSequence[2-redPos], thirdSequence[2-greenPos], thirdSequence[2-bluePos]);
    }

    function makeSequence(red:Float, green:Float, blue:Float):Float[]
    {
        redPos = 0;
        bluePos = 0;
        greenPos = 0;
        if(red>blue)
        {
            if(red>green)
            {
                if(blue>green)
                {
                    bluePos = 1;
                    greenPos = 2;
                    return [red, blue, green];
                }
                else
                {
                    greenPos = 1;
                    bluePos = 2;
                    return [red, green, blue];
                }
            }
            else
            {
                redPos = 1;
                bluePos = 2;
                return [green, red, blue];
            }
        }
        else
        {
            if(green>blue)
            {
                bluePos = 1;
                redPos = 2;
                var seq = [green, blue, red];
                return seq;
            }
            else
            {
                if(green>red)
                {
                    greenPos = 1;
                    redPos = 2;
                    return [blue, green, red];
                }
                else
                {
                    redPos = 1;
                    greenPos = 2;
                    return [blue, red, green];
                }
            }
        }
    }

    function max(red:Float, blue:Float, green:Float)
    {
        return Math.max(Math.max(red, blue), green);
    }

    public function create():Paint
    {
        var stops =
        [
            Stop
            {
                offset: 0.0
                color: firstColor
            }
            Stop
            {
                offset: 0.49
                color: secondColor;
            }
            Stop
            {
                offset: 0.5
                color: baseColor
            }
            Stop
            {
                offset: 1.0
                color: thirdColor
            }
        ];
        if(linearGradient)
        {
            return LinearGradient
            {
                    endX: linearEndX;
                    endY: linearEndY;
                    stops: stops;
            }
         }
         else
         {
            return RadialGradient
            {
                    centerX: radialCenterX;
                    centerY: radialCenterY;
                    stops: stops;
            }
         }

    }

}
